﻿#pragma once

#include "common.h"
#include "Random.h"
#include "Matrix.h"

struct SPCNsetting
{
	SPCNsetting() :
	isOutMtrInOneFile(false),isOutMtrInEachFile(false),
	isOutCond(true),isHistogramCond(true),isTableCond(true),
	usingDisk(true),usingMemory(false),isColorTable(true),
	usingThreading(true),isImportMtr(false){}

	bool isOutMtrInOneFile;		// Out
	bool isOutMtrInEachFile;
	bool isOutCond;
	bool isHistogramCond;		// Prsent
	bool isTableCond;
	bool isColorTable;
	bool isImportMtr;			// импортирована матрица или нет

	bool usingDisk;				// speed performance
	bool usingMemory;
	bool usingThreading;
};

struct CondStatistics
{
	CondStatistics()
	{
		maxCond=minCond=avrgCond=sumCond = 0.0;
		idMax=idMin = 0;
	}
	double	maxCond;	// Value
	long	idMax;		// idMatrix
	double	minCond;	// Value
	long	idMin;		// idMatrix
	double	avrgCond;
	double	sumCond;
	// частоты значений числа обусловленности
	std::map<int,val_Id> CondStat;
	double sumFreq;		// сумма частот
	double sumRelFreq;	// сумма относительных частот
	// данные для графика ф-ции распределения
	std::vector<distFunk> CondDistFunction;	
};

// законы распределния
enum distLaws
{
	lawExp,		 // 0 экспоненциональное
	lawNormal,	 // 1 нормальное
	lawCauchy,	 // 2 Коши
	lawLognormal,// 3 логнормальное
	lawUniform,	 // 4 равномерное
};

class CCoreSPCN
{
	int N_Perf;			// количество вычислений
	int m_Size;			// размерность матрицы
	double u,v;			// 
	double eps;			// точность 
	char *currLawName;	// имя текущего закона распределения
	distLaws currLaw;

	bool stopPerf;
	int id_Perform;		// индекс текущего вычисления

public:
	CCoreSPCN(void);
	~CCoreSPCN(void);
	// инициализация
	void Init();
	void Tergminate();
	
	// установить размерность матрицы
	void setMtrSize(int n){ m_Size = n; }
	// взять размер матрицы
	int getMtrSize(){ return m_Size; }
	// установить количество экспирементов
	void setNExp(int n){ N_Perf = n; }
	void setEpsStat(double e){ eps = e; }
	// взять количество вычислений
	int getPerfom(){ return N_Perf; }
	// взять индекс текущего вычислени
	int getNowPerfom(){ return id_Perform; }
	// взять имя закона распределения
	char* getLawName(){ return currLawName; }
	// взять индекс закона распределения
	distLaws getLaw(){ return currLaw; }

	// метод Якоби (метод вращений)
	void Jacobi( const uint n, double * const * a, 
				vector<double>& eigVal, double * const * v );
	// производится подготовка данных и выбор параметров выполнения
	int run();
	// выполняет серию экспериментов {A series of experiments}
	int PerformsCN();
	// останавливае серию вычислений
	int StopPerforms();

	// вычисление числа обусловленности
	void CondPerform();
	// анализирует полученные данные
	void CondAnаliz(int n);

	void sortCondUP();
	void sortCondDown();
	void unsortCond();

	double getMaxCond(){ return _statistic.maxCond; }
	double getMinCond(){ return _statistic.minCond; }
	double getSumCond(){ return _statistic.sumCond; }
	double getAvrgCond(){ return _statistic.avrgCond; }

	static unsigned WINAPI Thread_Process(void* pArguments);
	// генерация корреляционной матрицы
	void createMtr(CMatrix& m);

	// вывод числа обусловленности в файл
	int exportCondNum();
	int exportCondNum(char* nameFile);
	int exportCondNumToMatLab(char* nameFile);
	// выводит все сгенерированные корреляционные матрицы в файл
	int outAllMatrixToFile();
	int outAllMatrixToFile(char* nameFile);
	// выводит форматированные матрицы в консоль
	void outMtrToConsole(CMatrix m);
	// вывод текущую матрицу в текстовый файл
	// форматированную для использования в MatLab’е
	void outMtrFor_MatLab(CMatrix m);
	// удаляет все сгенерированные файлы
	int clearAllDataFile();
	// вывод матрицы в бинарный файл
	void outMtrToBinaryFile(CMatrix m);
	// очистка бинарного файла
	void clearDataFile();
	// чтение матриц из бинарного файла n-номер матрицы 0..N_Perform
	void readMtrFromFile(int n, CMatrix& m_);
	// чтение матрицы из памяти n-номер матрицы 0..N_Perform
	void readMtrFromMemory(int n, CMatrix& m);
	// импортирует матрицы из текстового файла (данные разделены пробелом
	// или знаком табуляции, дробная часть числа точкой
	int importMatix(char *fname);
	// указатель на ф-цию распределения для генерации матриц
	double (CCoreSPCN::* pCurrentDistLaw)();
	//void setDistLaw(int law);
	void setDistLaw(int law, ...);
	// законы распределения
	double distUniform();	// равномерный
	double distNormal();	// нормальный
	double distExp();		// экспоненциональный
	double distCauchy();	// коши
	double distLognorm();	// логнормальный

	void saveResult(char* nameFile);
	void loadResult(char *nameFile);

	std::vector<val_Id> CondNum;

	std::ofstream outDataFile;				// бинарный файл для хранения результатов
	std::map<int,std::vector<double> > eigVal;	// массив собственных значений
	//std::map<int,std::vector<double> >::iterator it;

	std::vector<CMatrix> _dataMtr;
	SPCNsetting setting;
	CondStatistics _statistic;
};

bool unsortCond (const val_Id& left, const val_Id& right);